package tr.edu.metu.is.mega.client.core;

import java.util.ArrayList;
import java.util.List;

import tr.edu.metu.is.mega.client.resource.MEGAResources;
import tr.edu.metu.is.mega.common.dto.BaseDTO;

import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.grid.ColumnData;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
import com.extjs.gxt.ui.client.widget.selection.StoreSelectionModel;
import com.extjs.gxt.ui.client.widget.table.DateTimeCellRenderer;
import com.extjs.gxt.ui.client.widget.toolbar.PagingToolBar;
import com.extjs.gxt.ui.client.widget.toolbar.PagingToolBar.PagingToolBarMessages;
import com.google.gwt.i18n.client.DateTimeFormat;

/**
 * Utility class for client side commonly used operations.
 */
public final class MegaUtil {

    private static GridCellRenderer<BeanModel> yesNoRenderer;

    private static GridCellRenderer<BeanModel> booleanRenderer;

    private static GridCellRenderer<BeanModel> dateRenderer;

    private static GridCellRenderer<BeanModel> baseDTORenderer;

    public static final String SHORT_DATE_STYLE = "1";

    public static final String LONG_DATE_STYLE = "2";

    public static final String LONG_DATE_FORMAT = "dd.MM.yyyy HH:mm";

    public static final String SHORT_DATE_FORMAT = "dd.MM.yyyy";

    /**
     * Hidden constructor.
     */
    private MegaUtil() {
    }

    /**
     * Evet, Hayir renderer.
     * 
     * @return GridCellRenderer
     */
    public static GridCellRenderer<BeanModel> getYesNoRenderer() {
        if (yesNoRenderer == null) {
            yesNoRenderer = new GridCellRenderer<BeanModel>() {

                @Override
                public Object render(BeanModel model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<BeanModel> store,
                        Grid<BeanModel> grid) {
                    Character yesNoChar = (Character) model.get(property);
                    return yesNoChar == null || yesNoChar.equals('N') ? MEGAResources.RESOURCEBUNDLE.no() : MEGAResources.RESOURCEBUNDLE.yes();
                }
            };
        }
        return yesNoRenderer;
    }

    /**
     * Boolean renderer.
     * 
     * @return GridCellRenderer
     */
    public static GridCellRenderer<BeanModel> getBooleanRenderer() {
        if (booleanRenderer == null) {
            booleanRenderer = new GridCellRenderer<BeanModel>() {

                @Override
                public Object render(BeanModel model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<BeanModel> store,
                        Grid<BeanModel> grid) {
                    Boolean value = (Boolean) model.get(property);
                    return value == null || !value ? MEGAResources.RESOURCEBUNDLE.no() : MEGAResources.RESOURCEBUNDLE.yes();
                }
            };
        }
        return booleanRenderer;
    }

    /**
     * Date renderer.
     * 
     * @return GridCellRenderer
     */
    public static GridCellRenderer<BeanModel> getDateRenderer() {
        final DateTimeFormat dateFormat = getShortDateFormat();
        final DateTimeCellRenderer<Grid<BeanModel>> dateCellRenderer = new DateTimeCellRenderer<Grid<BeanModel>>(dateFormat);

        if (dateRenderer == null) {
            dateRenderer = new GridCellRenderer<BeanModel>() {

                @Override
                public Object render(BeanModel model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<BeanModel> store,
                        Grid<BeanModel> grid) {
                    return dateCellRenderer.render(null, property, model.get(property));
                }
            };
        }
        return dateRenderer;
    }

    /**
     * Date renderer DateType : 1 Short DateType : Short.
     * 
     * @param dateType dateType
     * @return GridCellRenderer
     */
    public static GridCellRenderer<BeanModel> getDateRenderer(String dateType) {
        DateTimeFormat dateFormat = null;
        if (dateType.equals(SHORT_DATE_STYLE)) {
            dateFormat = getShortDateFormat();
        } else if (dateType.equals(LONG_DATE_STYLE)) {
            dateFormat = getLongDateFormat();
        }

        final DateTimeCellRenderer<Grid<BeanModel>> dateCellRenderer = new DateTimeCellRenderer<Grid<BeanModel>>(dateFormat);

        if (dateRenderer == null) {
            dateRenderer = new GridCellRenderer<BeanModel>() {

                @Override
                public Object render(BeanModel model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<BeanModel> store,
                        Grid<BeanModel> grid) {
                    return dateCellRenderer.render(null, property, model.get(property));
                }
            };
        }
        return dateRenderer;
    }

    /**
     * BaseDTO renderer.
     * 
     * @return GridCellRenderer
     */
    public static GridCellRenderer<BeanModel> getBaseDTORenderer() {
        if (baseDTORenderer == null) {
            baseDTORenderer = new GridCellRenderer<BeanModel>() {

                @Override
                public Object render(BeanModel model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<BeanModel> store,
                        Grid<BeanModel> grid) {
                    BeanModel beanModel = (BeanModel) model.get(property);
                    if (beanModel != null) {
                        BaseDTO baseDTO = beanModel.getBean();
                        return baseDTO.toString();
                    }
                    return null;
                }
            };
        }
        return baseDTORenderer;
    }

    /**
     * Decorade gridview using autoheight = true.
     * 
     * @param gridView The gridview that will be decorated.
     */
    public static void decoradeGridView(Grid<BeanModel> gridView) {
        decoradeGridViewWithAutoHeight(gridView, true);
    }

    /**
     * Decorade gridview using autoheight feature.
     * 
     * @param gridView The gridview that will be decorated.
     * @param useAutoHeight Use auto height
     */
    public static void decoradeGridViewWithAutoHeight(Grid<BeanModel> gridView, boolean useAutoHeight) {
        gridView.getView().setEmptyText(MEGAResources.RESOURCEBUNDLE.gridEmptyText());
        gridView.setLoadMask(true);
        gridView.setBorders(true);
        gridView.setStripeRows(true);
        gridView.setColumnLines(true);
        gridView.setAutoHeight(useAutoHeight);
        gridView.getView().setAutoFill(true);
        gridView.getView().setForceFit(true);
    }

    /**
     * @param pageSize pagesize
     * @return PagingToolBar
     */
    public static PagingToolBar getCommonPagingToolBar(int pageSize) {
        PagingToolBar pagingToolBar = new PagingToolBar(pageSize);
        PagingToolBarMessages messages = new PagingToolBarMessages();
        messages.setEmptyMsg(MEGAResources.RESOURCEBUNDLE.gridEmptyText());
        pagingToolBar.setMessages(messages);
        return pagingToolBar;
    }

    /**
     * ShortDate format.
     * 
     * @return DateTimeFormat
     */
    public static DateTimeFormat getShortDateFormat() {
        return DateTimeFormat.getFormat(SHORT_DATE_FORMAT);
    }

    /**
     * ShortDate format.
     * 
     * @return DateTimeFormat
     */
    public static DateTimeFormat getLongDateFormat() {
        return DateTimeFormat.getFormat(LONG_DATE_FORMAT);
    }

    /**
     * Returns selected items.
     * 
     * @param selectModel StoreSelectionModel
     * @param <T> selected item type
     * @return T return type
     */
    public static <T> List<T> getSelectedItems(StoreSelectionModel<BeanModel> selectModel) {
        List<T> selectedBeans = new ArrayList<T>(selectModel.getSelectedItems().size());
        if (selectModel.getSelectedItems().size() > 0) {
            List<BeanModel> selectedItems = selectModel.getSelectedItems();
            for (BeanModel beanModel : selectedItems) {
                T dto = beanModel.getBean();
                selectedBeans.add(dto);
            }
        }
        return selectedBeans;
    }

    /**
     * Get selected Item.
     * 
     * @param selectModel StoreSelectionModel
     * @param <T> selected item type
     * @return T return type
     */
    public static <T> T getSelectedItem(StoreSelectionModel<BeanModel> selectModel) {
        T selectedBean = null;
        if (selectModel.getSelectedItems().size() > 0) {
            selectedBean = selectModel.getSelectedItem().getBean();
        }
        return selectedBean;
    }
}
